﻿#region Copyright

// /*
// SilverlightInEnterprise
// SilverlightInEnterprise.Common
// CompositionProvider.cs
// 
// Author: Matt Van Horn
// Created 11/15/2011 6:59 PM
// Copyright: Silverlight in the Enterprise www.slinenterprise.com
// 
// Licensed under MS-PL http://www.opensource.org/licenses/MS-PL and while you 
// may use this in anyway you see fit and owe us nothing to do so, we wouldn't mind knowing that you got value out of the work we did (so we will do more) so 
// we ask that you leave a comment on www.slinenterprise.com or on the codeplex site slinenterprise.codeplex.com
// 
// */

#endregion

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Windows;
using SilverlightInEnterprise.Interfaces.Framework;

namespace SilverlightInEnterprise.Common.Framework
{
    public class CompositionProvider : ICompositionProvider
    {
        private readonly AggregateCatalog aggregateCatalog = new AggregateCatalog();
        private readonly CompositionContainer container;

        public CompositionContainer Container
        {
            get { return this.container; }
        }

        private const bool SIMPLE_COMPOSITION = true;

        public CompositionProvider()
        {
            this.container = new CompositionContainer(aggregateCatalog);
            this.aggregateCatalog.Catalogs.Add(new DeploymentCatalog());
            if (SIMPLE_COMPOSITION)
            {
                foreach (var part in Deployment.Current.Parts)
                {
                    if (part.Source.Contains("Modules"))
                    {
                        //this.aggregateCatalog.Catalogs.Add(new AssemblyCatalog((part as WindowsAssembly);
                        //AssemblyCatalog c = new AssemblyCatalog(Application.GetResourceStream());
                        var temp = Application.GetResourceStream(new Uri(part.Source, UriKind.Relative)).Stream;
                        //var c = new System.ComponentModel.Composition.Hosting.AssemblyCatalog()
                        //byte[] bytes = new byte[temp.Length];
                        //temp.Read(bytes, 0, (int) temp.Length - 1);
                        DeploymentCatalog c = new DeploymentCatalog("/ClientBin/" + part.Source.Replace(".dll", ".xap"));
                        c.DownloadCompleted += new EventHandler<AsyncCompletedEventArgs>(c_DownloadCompleted);
                        c.DownloadAsync();
                    }
                }
            }
        }

        private void c_DownloadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            this.aggregateCatalog.Catalogs.Add(sender as DeploymentCatalog);
        }

        public void LoadModule(Uri moduleUri, EventHandler<AsyncCompletedEventArgs> callback)
        {
            DeploymentCatalog catalog = new DeploymentCatalog(moduleUri);
            catalog.DownloadCompleted += OnDownloadCompleted;
            catalog.DownloadCompleted += callback;
            catalog.DownloadAsync();
        }

        private void OnDownloadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                throw e.Error;
            }
            aggregateCatalog.Catalogs.Add(sender as AggregateCatalog);
        }

        public void Compose(object attributedPart)
        {
            CompositionBatch batch = new CompositionBatch();
            batch.AddPart(attributedPart);
            this.container.Compose(batch);
        }

        public IEnumerable<Lazy<TExport, TMetadata>> GetExports<TExport, TMetadata>()
        {
            IEnumerable<Lazy<TExport, TMetadata>> exports = null;
            try
            {
                exports = this.container.GetExports<TExport, TMetadata>();
            }
            catch (Exception e)
            {
                throw e;
            }
            return exports;
        }

        public void Compose(CompositionBatch batch)
        {
            throw new NotImplementedException();
        }

        public Lazy<TExport, TMetadata> GetExport<TExport, TMetadata>()
        {
            Lazy<TExport, TMetadata> exports = null;
            try
            {
                exports = this.container.GetExport<TExport, TMetadata>();
            }
            catch (Exception e)
            {
                throw e;
            }
            return exports;
        }


        public T GetExportedValue<T>()
        {
            return this.container.GetExportedValueOrDefault<T>();
        }
    }
}